
/**
 * trait 练习
 */

pub trait Summary {
    fn summarize(&self) -> String {
        // 带实现的为trait方法的默认实现
        String::from("Read more...")
    }
    fn string(&self) -> String {
        String::from("It is me.")
    }
}

pub struct NewArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

impl Summary for NewArticle {
    fn summarize(&self) -> String {
        format!("{}, by {} ({})", self.headline, self.author, self.location)
    }

}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!("{}: {}", self.username, self.content)
    }
}

pub struct News {

}
impl Summary for News {
    // 空的impl，表示使用默认实现

    // 对默认实现的重写，叫重载
    fn string(&self) -> String {
        String::from("My name is News.")
    }
}

// trait作为参数：需要关键字impl、和trait名称
pub fn modify(item: &impl Summary) {
    println!("trait作为参数：{}", item.summarize());
}

// 
/**
 * impl Trait 很方便，适用于短小的例子。trait bound 则适用于更复杂的场景
 * 通过 + 指定多个 trait bound: 即同时需要实现多个trait
 * * pub fn notify(item: impl Summary + Display) {
 * * pub fn notify<T: Summary + Display>(item: T) {
 * 
 * 通过 where 简化 trait bound:
 *  fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {
 * 可以写成如下：
 *  fn some_function<T, U>(t: T, u: U) -> i32
    where T: Display + Clone,
          U: Clone + Debug
    {
 * 
 * 
 */

// trait作为参数的语法糖写法: trait bound
pub fn print<T: Summary> (item: &T) {
    println!("{}",item.string());
}

pub fn test() {
    println!("----------------trait练习---------------");

    let tweet = Tweet{
        username: String::from("Melody"),
        content: String::from("I'm learning Python."),
        reply: false,
        retweet: false,
    };
    println!("1 new tweet: {}", tweet.summarize());

    let news = News{};
    println!("news is : {}, name: {}", news.summarize(), news.string());
    
    modify(&tweet);
    print(&tweet);
}

